package com.litt.saap.util;

import com.mysql.jdbc.jdbc2.optional.MysqlDataSourceFactory;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.sql.*;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutionException;

/**
 * Main operation frame.
 * Created by simon on 2014/12/25.
 */
public class MainFrame
    implements ActionListener
{

    private JFrame frame;

    private JButton btnTest;
    private JButton btnInitDb;

    private MainPanel mainPanel;

    public void initGui() {
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        mainPanel = new MainPanel();
        mainPanel.initGui();
        frame.add(mainPanel, BorderLayout.CENTER);

        btnTest= new JButton("测试链接");
        btnTest.addActionListener(this);
        btnInitDb = new JButton("初始化数据库");
        btnInitDb.addActionListener(this);
        JPanel btnPanel = new JPanel();
        btnPanel.add(btnTest);
        btnPanel.add(btnInitDb);
        frame.add(btnPanel,BorderLayout.SOUTH);
        frame.pack();

    }

    public void show() {
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        MainFrame self = new MainFrame();
        self.initGui();
        self.show();

    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource().equals(btnTest)) {
            doTestConnection();
        } else if (e.getSource().equals(btnInitDb)) {
            doInitDb();
        }
    }

    /**
     * This method is used to read sql content from file and execute them.
     */
    private void doInitDb() {
        setEnable(false);
        SwingWorker<Boolean, Object> worker = new SwingWorker<Boolean, Object>() {
            private Boolean result = Boolean.FALSE;
            private int errorCount = 0;
            private Set<String> errorMsgSet=new HashSet<String>();

            @Override
            protected Boolean doInBackground() throws Exception {
                ensureMysqlDriver();
                try {
                    String url = "jdbc:mysql://"+mainPanel.getDbHost();
                    Connection connection = DriverManager.getConnection(url+"/mysql",  mainPanel.getUser(), mainPanel.getPassword());
                    createDatabase(connection);
                    connection.close();

                    connection = DriverManager.getConnection(url+"/"+mainPanel.getDbName(),  mainPanel.getUser(), mainPanel.getPassword());

                    File baseDir = new File(System.getProperty("user.dir"), "saap-web/src/main/dbscripts");
                    if (!baseDir.exists()) {
                        return Boolean.FALSE;
                    }
                    executeFile(connection, new File(baseDir, "init/database_saap_Mysql5.sql"));
                    executeFiles(connection,new File(baseDir,"init"), "INIT" );
                } catch (SQLException e) {
                    System.out.println("Failed to continue");
                    e.printStackTrace();
                    throw e;
                } catch (IOException e) {
                    System.out.println("Failed to continue");
                    e.printStackTrace();
                    throw e;
                }
                this.result = Boolean.TRUE;

                return Boolean.TRUE;
            }

            private void executeFiles(Connection connection, File file, String str) throws IOException, SQLException {
                File[] files = file.listFiles();
                if (null == files || 0 == files.length) {
                    return;
                }
                for(File f: files) {
                    if (f.isFile() && f.getName().contains(str)) {
                        executeFile( connection,f);
                    }
                }
            }

            private void executeFile(Connection connection, File file) throws IOException, SQLException {
                String content = FileUtils.readFileToString(file);
                String[] queries = StringUtils.split(content,";");
                Statement st = null;
                try {
                    st = connection.createStatement();
                    for(String l : queries) {
                        String str = StringUtils.trimToNull(l);
                        if (null!= str) {
                            try {
                                st.execute(str);
                            } catch(Exception e) {
                                System.err.println(" sql :"+str);
                                e.printStackTrace();
                                this.errorCount++;
                            }
                        }
                    }

                } finally {
                    if (null != st) {
                        st.close();
                    }
                }
            }

            private void createDatabase(Connection connection) throws SQLException {
                Statement st = null;
                try {
                    st = connection.createStatement();
                    st.execute("create database " + mainPanel.getDbName() + " default character set utf8");
                } catch (SQLException e) {
                    e.printStackTrace();
                } finally {
                    if (null != st) {
                        st.close();
                    }
                }
            }

            @Override
            protected void done() {
                super.done();
                if (Boolean.TRUE.equals(this.result)) {
                    JOptionPane.showMessageDialog(frame, "执行初始化脚本完成:\n共"+errorCount+"个错误");
                } else {
                    JOptionPane.showMessageDialog(frame, "执行初始化脚本失败");
                }
                setEnable( true );
            }
        };
        worker.execute();
    }

    private void ensureMysqlDriver() throws IllegalAccessException, InstantiationException, SQLException {
        boolean has = false;
        try {
            Driver driver = DriverManager.getDriver("jdbc:mysql");
            if (null != driver) {
                has = true;
            }
        } catch (SQLException e) {
//            e.printStackTrace();
            // Just ignore this exception.
        }

        if (!has) {
            DriverManager.registerDriver(com.mysql.jdbc.Driver.class.newInstance());
        }
    }

    private void doTestConnection() {
        setEnable(false);
        SwingWorker<Boolean,Object> worker = new SwingWorker<Boolean, Object>() {
            @Override
            protected Boolean doInBackground() throws Exception {
                ensureMysqlDriver();
                String url = "jdbc:mysql://"+mainPanel.getDbHost();
                Connection connection = null;
                Statement st = null;
                ResultSet rs = null;

                try {
                    connection = DriverManager.getConnection(url+"/mysql", mainPanel.getUser(), mainPanel.getPassword());
                    st = connection.createStatement();
                    rs = st.executeQuery("select 1");
                    if (rs.next()) {
                        System.out.println(rs.getInt(1));
                    }

                    return Boolean.TRUE;
                } catch (SQLException e) {
                    e.printStackTrace();
                } finally{
                    if (rs != null) {
                        rs.close();
                    }
                    if (st != null) {
                        st.close();
                    }
                    if (connection!=null) {
                        connection.close();
                    }
                }
                return Boolean.FALSE;
            }

            @Override
            protected void done() {
                Boolean obj = Boolean.FALSE;
                try {
                    obj = this.get();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
                if (Boolean.TRUE.equals(obj)) {
                    JOptionPane.showMessageDialog(frame, "链接成功");
                } else {
                    JOptionPane.showMessageDialog(frame, "链接失败");
                }
                setEnable(true);
            }
        };
        worker.execute();
    }

    private void setEnable(boolean flag) {
        mainPanel.setEnable(flag);
        btnInitDb.setEnabled(flag);
        btnTest.setEnabled(flag);
    }
}
